﻿using System.Collections.Generic;
using System.Text;
#if API
using HttpEn = HIHS.Net.Http.HttpApiClient;
#else
using HttpEn = VersionManage.Logic.WebLogic;
#endif
namespace VersionManage.Logic
{
    public class Utility
    {
        public string BaseAddress
        {
            get;
            protected set;
        }
        public List<string> Headers
        {
            get;
            protected set;
        }

        public void AddHeaders(string value)
        {
            if (Headers == null)
                Headers = new List<string>();
            Headers.Add(value);
        }

        /// <summary>
        /// 在Request创建前调用些函数
        /// 子类可重写此方法
        /// </summary>
        /// <param name="item"></param>
        public virtual void RequestCreating(HttpItem item)
        {
            if (requestCreatingEvent != null)
                requestCreatingEvent(this, item);
        }

        private event RequestCreateIngEventHandler requestCreatingEvent;

        /// <summary>
        /// 当需要创建请求时执行
        /// </summary>
        public event RequestCreateIngEventHandler RequestCreatingEvent
        {
            add
            {
                requestCreatingEvent += value;
            }
            remove
            {
                requestCreatingEvent -= value;
            }
        }


        #region 使用Attribute参数请求服务器
        /// <summary>
        /// HttpResult
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="R"></typeparam>
        /// <param name="t"></param>
        /// <param name="method"></param>
        /// <returns></returns>
        public HttpResult<R> GetHttpResult<T, R>(T t, HttpMethod method = HttpMethod.Get)
        {
            object[] atts = typeof(T).GetCustomAttributes(typeof(RequestParamterAttribute), true);
            string url = "";
            string[] headers = null;
            string contentType = "application/json";
            if (atts.Length > 0)
            {
                RequestParamterAttribute rp = (RequestParamterAttribute)atts[0];
                method = rp.Method;
                //if (method == HttpMethod.Post)
                contentType = rp.ContentType;
                headers = rp.Headers;
                if (rp.Relative)
                    url += rp.Url;
                else
                    url = rp.Url;
            }

            switch (method)
            {
                case HttpMethod.Put:
                    return HttpPutResult<T, R>(t, url, headers: headers, contentType: contentType);
                case HttpMethod.Head:
                    return HttpHeadResult<T, R>(t, url, headers: headers, contentType: contentType);
                case HttpMethod.Delete:
                    return HttpDeleteResult<T, R>(t, url, headers: headers, contentType: contentType);
            }
            return new HttpResult<R>(false, "", "");
        }

        public object GetResult<T>(T t, HttpMethod method = HttpMethod.Get)
        {
            HttpResult<object> hr = GetHttpResult<T, object>(t, method: method);
            return hr.Content;
        }

        #endregion





        #region Put

        protected virtual HttpResult<R> HttpPutResult<T, R>(T t, string url, string[] headers = null, string contentType = "application/json")
        {
            HttpItem item = CreatePutHttpItem(t, url, headers, contentType);
            this.RequestCreating(item);
            if (!item.Cancel)
                return HttpEn.GetHttpResult<R>(item);
            else
                return new HttpResult<R>(false, "-1", "请求被取消");
        }

        #endregion

        #region Head
        public HttpResult<R> HttpHeadResult<T, R>(T t, string url, string[] headers = null, string contentType = "application/json")
        {
            HttpItem item = CreatePutHttpItem(t, url, headers, contentType);
            item.Method = HttpMethod.Head;
            this.RequestCreating(item);
            if (!item.Cancel)
                return HttpEn.GetHttpResult<R>(item);
            else
                return new HttpResult<R>(false, "-1", "请求被取消");
        }

        #endregion

        #region Delete
        public HttpResult<R> HttpDeleteResult<T, R>(T t, string url, string[] headers = null, string contentType = "application/json")
        {
            HttpItem item = CreatePutHttpItem(t, url, headers, contentType);
            item.Method = HttpMethod.Delete;
            this.RequestCreating(item);
            if (!item.Cancel)
                return HttpEn.GetHttpResult<R>(item);
            else
                return new HttpResult<R>(false, "-1", "请求被取消");
        }

        #endregion


        #region 公用
        private HttpItem CreateHttpItem(object obj, string url, string[] headers, string contentType, HttpMethod method)
        {
            HttpItem item = new HttpItem();
            item.ContentObject = obj;
            item.ContentType = contentType;
            item.Url = BaseAddress + url;
            if (headers != null)
                item.Headers.AddRange(headers);
            item.Method = method;
            return item;
        }

        private HttpItem CreatePutHttpItem(object obj, string url, string[] headers, string contentType )
        {
            HttpItem item = CreateHttpItem(obj, url, headers, contentType, HttpMethod.Put);
            if (obj == null)
                return item;
            System.Reflection.PropertyInfo[] pinfos = obj.GetType().GetProperties();
            if (pinfos != null && pinfos.Length > 0)
            {
                foreach (var pinfo in pinfos)
                {
                    object[] atts = pinfo.GetCustomAttributes(typeof(RequestPropertyAttribute), false);
                    if (atts == null || atts.Length == 0)
                    {
                        item.Headers.Add(string.Format("{0}: {1}", pinfo.Name, pinfo.GetValue(obj, null)));
                        continue;
                    }
                    RequestPropertyAttribute rpa = (RequestPropertyAttribute)atts[0];
                    switch (rpa.Type)
                    {
                        case PropertyType.Body:
                            item.Content = (byte[])pinfo.GetValue(obj, null);
                            break;
                        case PropertyType.Url:
                            item.Url += pinfo.GetValue(obj, null);
                            break;
                        case PropertyType.Head:
                        case PropertyType.Parameter:
                            string name = rpa.Name != null ? rpa.Name : pinfo.Name;
                            item.Headers.Add(string.Format("{0}: {1}", rpa.Name, pinfo.GetValue(obj, null)));
                            break;
                    }
                }
            }
            return item;
        }

        private HttpItem CreateGetHttpItem(object obj, string url, string[] headers, string contentType)
        {
            HttpItem item = CreateHttpItem(obj, url, headers, contentType, HttpMethod.Get);
            if (obj == null)
                return item;
            System.Reflection.PropertyInfo[] pinfos = obj.GetType().GetProperties();
            if (pinfos != null && pinfos.Length > 0)
            {
                StringBuilder sb = new StringBuilder();
                foreach (var pinfo in pinfos)
                {
                    object[] atts = pinfo.GetCustomAttributes(typeof(RequestPropertyAttribute), false);
                    if (atts == null || atts.Length == 0)
                    {
                        sb.Append(string.Format("{0}={1}&", pinfo.Name, pinfo.GetValue(obj, null)));
                        continue;
                    }
                    RequestPropertyAttribute rpa = (RequestPropertyAttribute)atts[0];
                    switch (rpa.Type)
                    {
                        case PropertyType.Body:
                            item.Content = (byte[])pinfo.GetValue(obj, null);
                            break;
                        case PropertyType.Url:
                            item.Url += pinfo.GetValue(obj, null);
                            break;
                        case PropertyType.Head:
                            string name = rpa.Name != null ? rpa.Name : pinfo.Name;
                            item.Headers.Add(string.Format("{0}: {1}", name, pinfo.GetValue(obj, null)));
                            break;
                        case PropertyType.Parameter:
                            sb.Append(string.Format("{0}={1}&", pinfo.Name, pinfo.GetValue(obj, null)));
                            break;
                    }
                }
                if(sb.Length>0)
                    item.Url+="?"+sb.ToString();
            }
            return item;
        }



        #endregion


        public HttpResult<R> GetHttpResult<R>(HttpItem item)
        {
            return HttpEn.GetHttpResult<R>(item);
        }
    }


    public delegate void RequestCreateIngEventHandler(object obj, HttpItem item);
}
